package com.bwie.auth.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.alibaba.fastjson.JSONObject;
import com.bwie.auth.feign.SysLogin;
import com.bwie.auth.service.AuthService;
import com.bwie.auth.utils.TelSmsUtils;
import com.bwie.common.constants.JwtConstants;
import com.bwie.common.constants.TokenConstants;
import com.bwie.common.domain.Login;
import com.bwie.common.domain.request.LoginRequest;
import com.bwie.common.domain.response.JwtResponse;
import com.bwie.common.result.Result;
import com.bwie.common.utils.JwtUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

/**
 * @Author：Minxiao Hao
 * @Description:
 * @name：AuthServiceImpl
 * @Date：2024/11/4 10:11
 */
@Service
public class AuthServiceImpl implements AuthService {
    @Autowired
    private SysLogin sysLogin;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private HttpServletRequest request;
    @Autowired
    private TelSmsUtils telSmsUtils;

    /**
     * 生成验证码
     * @param loginPhone
     */
    @Override
    public void findAuthName(String loginPhone) {
        //手机号判空(手机号非空校验)
        if(StringUtils.isBlank(loginPhone)){
            throw new RuntimeException("手机号不能为空");
        }
        //手机号正则(手机号格式判断)
        Pattern compile = Pattern.compile("(?:(?:\\+|00)86)?1(?:(?:3[\\d])|(?:4[5-79])|(?:5[0-35-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\\d])|(?:9[189]))\\d{8}$");
        if (!compile.matcher(loginPhone).matches()){
            throw new RuntimeException("手机号格式不正确");
        }
        //判断查询 手机号是否存在
        Result<Login> loginPhone1 = sysLogin.findLoginPhone(loginPhone);
        if (null==loginPhone1){
            throw new RuntimeException("手机号不存在,请注册后再进行验证");
        }
        //生成随机验证码
        String loginCode = RandomUtil.randomNumbers(4);
        //将验证码存储到Redis中
        redisTemplate.opsForValue().set(loginPhone,loginCode,30, TimeUnit.MINUTES);
        //发送
        telSmsUtils.sendSms(loginPhone,new HashMap<String ,String>(){{
            put("loginCode",loginCode);
        }});
    }

    /**
     * 登录
     * @param loginRequest
     * @return
     */
    @Override
    public JwtResponse findAuthPhone(LoginRequest loginRequest) {
        //根据是实体类获取 手机号和验证码
        String loginPhone = loginRequest.getLoginPhone();
        String loginCode = loginRequest.getLoginCode();
        //手机号判空
        if (com.bwie.common.utils.StringUtils.isAnyBlank(loginPhone,loginCode)){
            throw new RuntimeException("手机号或者验证码不能为空");
        }
        //判断手机号是否存在
        Result<Login> login = sysLogin.findLoginPhone(loginPhone);
        if (null == login){
            throw new RuntimeException("手机号未注册,请先注册");
        }
        //判断验证码是否正确
        String loginCode1 = (String) redisTemplate.opsForValue().get(loginPhone);
        if (StringUtils.isBlank(loginCode1)){
            throw new RuntimeException("请先发送验证码");
        }
        if (!loginCode1.equals(loginCode)){
            throw new RuntimeException("验证码错误");
        }
        //登录成功 -> 生成token
        Map<String, Object> claims = new HashMap<>();
        String userKey = UUID.randomUUID().toString();
        claims.put(JwtConstants.USER_KEY, userKey);
        String token = JwtUtils.createToken(claims);
        //存储用户信息
        redisTemplate.opsForValue().set(TokenConstants.LOGIN_TOKEN_KEY + userKey, JSONObject.toJSONString(login),30,TimeUnit.MINUTES);
        //登陆成功
        JwtResponse jwtResponse = new JwtResponse();
        jwtResponse.setToken(token);
        jwtResponse.setExpireTime("30MIN");
        return jwtResponse;
    }
    /**
     * 反序列化
     * @return
     */
    @Override
    public Login findLoginInfo() {
        //获取请求头重的token
        String token = request.getHeader(TokenConstants.TOKEN);
        //解析出loginKey
        String userKey = JwtUtils.getUserKey(token);
        //获取redis中存储的用户的信息
        String loginJsonStr = redisTemplate.opsForValue().get(TokenConstants.LOGIN_TOKEN_KEY + userKey);
        //反序列化成SysLogin
        return JSONObject.parseObject(loginJsonStr,Login.class);
    }
}
